/*
 * Copyright 2011 www.pretty-tools.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include "StdAfx.h"
#include "RulesUpdateManager.h"

RulesUpdateManager::Profile::Profile(LPCWSTR pszName)
{
    CComPtr<IDirectoryService> pDirectoryService;
    if (FAILED(pDirectoryService.CoCreateInstance(L"XPCOMAdapter.DirectoryService.1")))
        return;

    CComVariant vtResult;
    if (FAILED(pDirectoryService->get(CComBSTR(L"ProfD"), CComBSTR(L"{F75B5C32-B42D-416D-93AC-8798869674CE}"), &vtResult)) || VT_DISPATCH != vtResult.vt)
        return;

    CComQIPtr<ILocalFile> pProfileDirectory = vtResult.pdispVal;
    if (!pProfileDirectory)
        return;

    if (FAILED(pProfileDirectory->append(CComBSTR(L"WebSlideShow"))))
        return;

    VARIANT_BOOL vbExists = VARIANT_FALSE;
    if (SUCCEEDED(pProfileDirectory->exists(&vbExists)) && (VARIANT_FALSE == vbExists))
        pProfileDirectory->create(1/*DIRECTORY_TYPE*/, 0);

    if (FAILED(pProfileDirectory->append(CComBSTR((CStringW)pszName + L".xml"))))
        return;

    Attach(pProfileDirectory.Detach());
}

RulesUpdateManager::Profile RulesUpdateManager::GetPredefinedProfile()
{
    return Profile( _T("PredefinedProfile") );
}

RulesUpdateManager::Profile RulesUpdateManager::GetSubscriptionProfile()
{
    return Profile( _T("Subscriptions") );
}

RulesUpdateManager::Profile RulesUpdateManager::GetProfile(LPCWSTR pszName)
{
    return Profile(pszName);
}

COleDateTime RulesUpdateManager::ConvertStringToTime(LPCTSTR pszDate)
{
    COleDateTime dt;
    if (!pszDate || !*pszDate)
        dt = 0.;
    else if (!dt.ParseDateTime(pszDate, 0, LANG_ENGLISH))
        dt.ParseDateTime(pszDate, 0);

    return dt;
}

void RulesUpdateManager::PredefinedProfileUpdateThread::onData(const CStringA& strData, const CString& strLastModified)
{
    if (strData.IsEmpty())
        return;

    CString strPath = RulesUpdateManager::GetPredefinedProfile().GetPath();
    if (strPath.IsEmpty())
        return;

    File f;
    if (f.Create(strPath))
        f.Write((LPCSTR)strData, strData.GetLength());

    //TODO: check and disableJavaScript

    Configuration().predefinedRulesLastModified = strLastModified;
}

void RulesUpdateManager::SubscriptionUpdateThread::onData(const CStringA& strData, const CString& strLastModified)
{
    if (!strLastModified.IsEmpty()) m_subscription.lastModified = strLastModified;

    Subscriptions subscriptions;
    CString strSubscriptionsPath = RulesUpdateManager::GetSubscriptionProfile().GetPath();
    subscriptions.LoadFromFile(strSubscriptionsPath);
    int idx = subscriptions.FindIndexByName(m_subscription.name);
    if (idx == -1)
        subscriptions.subscriptions.Add(m_subscription);
    else
        subscriptions.subscriptions[idx] = m_subscription;
    subscriptions.SaveToFile(strSubscriptionsPath);

    if (strData.IsEmpty())
        return;

    //TODO: check and disableJavaScript

    CString strPath = RulesUpdateManager::GetProfile(m_subscription.name).GetPath();
    if (strPath.IsEmpty())
        return;

    File f;
    if (f.Create(strPath))
        f.Write((LPCSTR)strData, strData.GetLength());
}

void RulesUpdateManager::CheckForPredefinedRulesUpdate()
{
    Configuration wsshConfig;

    if (!wsshConfig.updatePredefinedRules)
        return;

    if (!GetPredefinedProfile().Exists())
    {
        wsshConfig.updateTimeStamp = L"";
        wsshConfig.predefinedRulesLastModified = L"";
    }

    COleDateTime updateTimeStamp = ConvertStringToTime(wsshConfig.updateTimeStamp);
    ATLTRACE( _T("CheckForPredefinedRulesUpdate: updateTimeStamp=%s\n"), updateTimeStamp.Format(LOCALE_NOUSEROVERRIDE, LANG_ENGLISH) );

    COleDateTime curDate = COleDateTime::GetCurrentTime();
    DATE updateInterval = 60 * wsshConfig.updateInterval;

    if ((curDate - updateTimeStamp).GetTotalSeconds() < updateInterval)
        return;

    ATLTRACE("checkForPredefinedRulesUpdate: need to update predefined rules\n");
    // change timestamp to prevent updates
    wsshConfig.updateTimeStamp = curDate.Format( _T("%B %d, %Y %H:%M:%S") );

    (new PredefinedProfileUpdateThread())->Start();
}

void RulesUpdateManager::CheckForSubscriptionUpdate(LPCTSTR pszSubscription)
{
    if (!pszSubscription || !*pszSubscription)
        return;

    Configuration wsshConfig;

    Subscriptions subscriptions;
    subscriptions.LoadFromFile(RulesUpdateManager::GetSubscriptionProfile().GetPath());

    Subscription subscription = subscriptions.FindByName(pszSubscription);
    if (!subscription)
    {
        subscription = Subscription(pszSubscription);
        subscription.url = wsshConfig.urlSubscriptions + pszSubscription + _T(".xml");
    }

    COleDateTime updateTimeStamp = ConvertStringToTime(subscription.updateTimeStamp);

    COleDateTime curDate = COleDateTime::GetCurrentTime();
    DATE updateInterval = 60 * wsshConfig.updateInterval;

    if ((curDate - updateTimeStamp).GetTotalSeconds() < updateInterval)
        return;

    // need to update subscription
    ATLTRACE("checkForSubscriptionUpdate: need to update subscription\n");
    // change timestamp to prevent updates
    subscription.updateTimeStamp = curDate.Format( _T("%B %d, %Y %H:%M:%S") );

    (new SubscriptionUpdateThread(subscription))->Start();
}
